<script lang="ts" setup>
import { computed, h, reactive, ref, watch } from 'vue';
import { useRoute, useRouter } from 'vue-router';
import { Card, Form, Input, Select, DatePicker, Button, Table, Tag, message, Space, Upload, Modal } from 'ant-design-vue';
import type { TableColumnsType, UploadFile } from 'ant-design-vue';

import {
  getTenantTaskApplicationsApi,
  manualCreateTenantTaskApplicationApi,
  previewTenantTaskApplicationContractApi,
  type TaskApi,
} from '#/api/core/task';
import { getFreelancerListApi, type FreelancerApi } from '#/api/core/freelancer';

type DateRangeValue = [string, string] | [];

const route = useRoute();
const router = useRouter();

const tenantId = ref<string>('');
const taskId = ref<string>('');
const tenantName = ref<string>(typeof route.query.tenantName === 'string' ? route.query.tenantName : '');
const taskName = ref<string>(typeof route.query.taskName === 'string' ? route.query.taskName : '');

const loading = ref(false);

const applications = ref<TaskApi.TaskApplicationRecord[]>([]);
const taskInfo = ref<TaskApi.TaskRecord | null>(null);

const pagination = reactive({
  current: 1,
  pageSize: 10,
  total: 0,
});

const filters = reactive({
  search: '',
  status: '' as string | '',
});

const appliedRange = ref<DateRangeValue>([]);

const statusOptions = [
  { label: '待审核', value: 'pending' },
  { label: '已通过', value: 'approved' },
  { label: '已拒绝', value: 'rejected' },
  { label: '已取消', value: 'cancelled' },
  { label: '已离岗', value: 'dimission' },
];

const statusTagMap: Record<string, { color: string; text: string }> = {
  pending: { color: 'gold', text: '待审核' },
  approved: { color: 'green', text: '已通过' },
  rejected: { color: 'red', text: '已拒绝' },
  cancelled: { color: 'default', text: '已取消' },
  dimission: { color: 'purple', text: '已离岗' },
};

const manualModalVisible = ref(false);
const manualFileList = ref<UploadFile[]>([]);
const manualSubmitting = ref(false);
const manualFreelancerKeyword = ref('');
const manualFreelancerLoading = ref(false);
const manualFreelancerOptions = ref<Array<{ label: string; value: string; record: FreelancerApi.FreelancerRecord }>>([]);
const manualSelectedFreelancerId = ref<string>('');

const previewModalVisible = ref(false);
const previewUrl = ref<string | null>(null);
const previewLoading = ref(false);
const previewRecord = ref<TaskApi.TaskApplicationRecord | null>(null);

const cardTitle = computed(() => {
  if (taskName.value) {
    return `任务报名 - ${taskName.value}`;
  }
  if (taskInfo.value?.name) {
    return `任务报名 - ${taskInfo.value.name}`;
  }
  return '任务报名';
});

const previewTitle = computed(() =>
  previewRecord.value ? `合同预览 - ${previewRecord.value.name}` : '合同预览',
);

const tablePagination = computed(() => ({
  current: pagination.current,
  pageSize: pagination.pageSize,
  total: pagination.total,
  showSizeChanger: true,
  showQuickJumper: true,
  showTotal: (total: number) => `共 ${total} 条`,
}));

const formatDateTime = (value?: string | null) => {
  if (!value) {
    return '—';
  }
  const date = new Date(value);
  if (Number.isNaN(date.getTime())) {
    return value;
  }
  const pad = (num: number) => (num < 10 ? `0${num}` : `${num}`);
  return `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())} ${pad(
    date.getHours(),
  )}:${pad(date.getMinutes())}:${pad(date.getSeconds())}`;
};

const handlePreviewContract = async (record: TaskApi.TaskApplicationRecord) => {
  if (!tenantId.value || !taskId.value) {
    message.error('缺少任务信息，无法查看合同');
    return;
  }

  previewRecord.value = record;
  if (previewUrl.value) {
    URL.revokeObjectURL(previewUrl.value);
    previewUrl.value = null;
  }

  previewModalVisible.value = true;
  previewLoading.value = true;

  try {
    const blob = await previewTenantTaskApplicationContractApi(
      tenantId.value,
      taskId.value,
      record.id,
    );
    previewUrl.value = URL.createObjectURL(blob);
  } catch (error) {
    console.error('获取合同文件失败', error);
    message.error('获取合同失败，请稍后重试');
    closePreviewModal();
  } finally {
    previewLoading.value = false;
  }
};

const closePreviewModal = () => {
  previewModalVisible.value = false;
  previewLoading.value = false;
  if (previewUrl.value) {
    URL.revokeObjectURL(previewUrl.value);
    previewUrl.value = null;
  }
  previewRecord.value = null;
};

const columns: TableColumnsType<TaskApi.TaskApplicationRecord> = [
  { title: '报名编号', dataIndex: 'application_number', key: 'application_number', width: 180, ellipsis: true },
  { title: '姓名', dataIndex: 'name', key: 'name', width: 140 },
  { title: '手机号', dataIndex: 'phone', key: 'phone', width: 160 },
  {
    title: '状态',
    dataIndex: 'status',
    key: 'status',
    width: 120,
    customRender: ({ record }) => {
      const status = statusTagMap[record.status] ?? { color: 'default', text: record.status ?? '未知' };
      return h(Tag, { color: status.color }, () => status.text);
    },
  },
  {
    title: '报名时间',
    dataIndex: 'applied_at',
    key: 'applied_at',
    width: 200,
    customRender: ({ record }) => formatDateTime(record.applied_at),
  },
  {
    title: '处理时间',
    dataIndex: 'processed_at',
    key: 'processed_at',
    width: 200,
    customRender: ({ record }) => formatDateTime(record.processed_at),
  },
  {
    title: '处理人',
    dataIndex: ['processor', 'name'],
    key: 'processor',
    width: 160,
    customRender: ({ record }) => record.processor?.name || '—',
  },
  {
    title: '操作',
    key: 'actions',
    width: 140,
    fixed: 'right',
    customRender: ({ record }) => {
      if (record.status !== 'approved') {
        return h('span', { style: { color: '#94a3b8' } }, '—');
      }
      return h(
        Button,
        {
          type: 'link',
          size: 'small',
          onClick: () => handlePreviewContract(record),
        },
        () => '查看合同',
      );
    },
  },
];

const fetchApplications = async (tid: string, tskId: string) => {
  if (!tid || !tskId) return;

  loading.value = true;
  try {
    const [start, end] = Array.isArray(appliedRange.value) ? appliedRange.value : [];
    const response = await getTenantTaskApplicationsApi(tid, tskId, {
      page: pagination.current,
      per_page: pagination.pageSize,
      search: filters.search.trim() || undefined,
      status: filters.status || undefined,
      applied_start: start || undefined,
      applied_end: end || undefined,
    });

    if (response.task) {
      const rawTask = response.task;
      taskInfo.value = {
        ...rawTask,
        id: String(rawTask.id ?? ''),
        tenant_id: String(rawTask.tenant_id ?? tid),
      };
      taskName.value = taskName.value || taskInfo.value.name || '';
    } else {
      taskInfo.value = null;
    }

    const appData = response.applications;
    applications.value = (appData.data ?? []).map((item) => ({
      ...item,
      id: String(item.id),
      task_id: String(item.task_id),
      tenant_id: String(item.tenant_id),
      freelancer_id: item.freelancer_id ? String(item.freelancer_id) : null,
    }));
    pagination.total = appData.total ?? 0;
    pagination.current = appData.current_page ?? pagination.current;
    if (appData.per_page) {
      pagination.pageSize = Number(appData.per_page);
    }
  } catch (error) {
    console.error('获取任务报名列表失败', error);
    message.error('获取任务报名列表失败，请稍后重试');
  } finally {
    loading.value = false;
  }
};

const handleSearch = () => {
  pagination.current = 1;
  fetchApplications(tenantId.value, taskId.value);
};

const handleReset = () => {
  filters.search = '';
  filters.status = '';
  appliedRange.value = [];
  pagination.current = 1;
  fetchApplications(tenantId.value, taskId.value);
};

const handleTableChange = (pag: { current?: number; pageSize?: number }) => {
  pagination.current = pag.current ?? pagination.current;
  pagination.pageSize = pag.pageSize ?? pagination.pageSize;
  fetchApplications(tenantId.value, taskId.value);
};

const handleBack = () => {
  router.push({
    name: 'TenantTaskList',
    params: { tenantId: tenantId.value },
    query: { tenantName: tenantName.value },
  });
};

const openManualModal = () => {
  if (!tenantId.value || !taskId.value) {
    message.warning('当前任务信息缺失，无法手动录入');
    return;
  }
  manualModalVisible.value = true;
};

const resetManualModal = () => {
  manualModalVisible.value = false;
  manualFileList.value = [];
  manualSubmitting.value = false;
  manualFreelancerKeyword.value = '';
  manualFreelancerOptions.value = [];
  manualSelectedFreelancerId.value = '';
  manualFreelancerLoading.value = false;
};

const handleManualUploadChange = (info: { fileList: UploadFile[] }) => {
  const latestList = info.fileList.slice(-1);
  manualFileList.value = latestList.map((file) => ({
    ...file,
    status: 'done',
  }));
};

const handleManualUploadRemove = () => {
  manualFileList.value = [];
  return true;
};

const handleManualSubmit = async () => {
  if (!tenantId.value || !taskId.value) {
    message.error('缺少任务信息，无法录入');
    return;
  }
  if (!manualSelectedFreelancerId.value) {
    message.error('请选择需要关联的C端用户');
    return;
  }

  const fileRecord = manualFileList.value[0];
  const rawFile = fileRecord?.originFileObj as File | undefined;
  if (!rawFile) {
    message.error('请先上传合同扫描件');
    return;
  }

  manualSubmitting.value = true;
  try {
    const formData = new FormData();
    formData.append('contract_file', rawFile);
    formData.append('freelancer_id', manualSelectedFreelancerId.value);
    await manualCreateTenantTaskApplicationApi(tenantId.value, taskId.value, formData);
    message.success('手动录入成功');
    resetManualModal();
    fetchApplications(tenantId.value, taskId.value);
  } catch (error) {
    console.error('手动录入失败', error);
    message.error('手动录入失败，请稍后重试');
  } finally {
    manualSubmitting.value = false;
  }
};

const handleFreelancerSearch = async () => {
  const keyword = manualFreelancerKeyword.value.trim();
  if (!keyword) {
    message.warning('请输入手机号或姓名后再搜索');
    return;
  }

  manualFreelancerLoading.value = true;
  try {
    const isNumeric = /^\d+$/.test(keyword);
    const params: FreelancerApi.FreelancerListParams = {
      page: 1,
      per_page: 20,
    };
    if (isNumeric) {
      params.phone = keyword;
    } else {
      params.name = keyword;
    }
    const response = await getFreelancerListApi(params);
    manualFreelancerOptions.value = (response.data ?? []).map((freelancer) => ({
      label: `${freelancer.name} / ${freelancer.phone}`,
      value: String(freelancer.id),
      record: freelancer,
    }));
    if (!manualFreelancerOptions.value.length) {
      message.info('未找到匹配的C端用户');
    }
  } catch (error) {
    console.error('搜索C端用户失败', error);
    message.error('搜索失败，请稍后重试');
  } finally {
    manualFreelancerLoading.value = false;
  }
};

watch(
  () => route.params.taskId,
  (newVal) => {
    taskId.value = newVal ? String(newVal) : '';
    pagination.current = 1;
    if (tenantId.value && taskId.value) {
      fetchApplications(tenantId.value, taskId.value);
    } else {
      applications.value = [];
    }
  },
  { immediate: true },
);

watch(
  () => route.params.tenantId,
  (newVal) => {
    tenantId.value = newVal ? String(newVal) : '';
    if (!tenantId.value) {
      applications.value = [];
      taskInfo.value = null;
      return;
    }
    if (taskId.value) {
      fetchApplications(tenantId.value, taskId.value);
    }
  },
  { immediate: true },
);

watch(
  () => route.query.taskName,
  (newVal) => {
    if (typeof newVal === 'string') {
      taskName.value = newVal;
    }
  },
  { immediate: true },
);

watch(
  () => route.query.tenantName,
  (newVal) => {
    if (typeof newVal === 'string') {
      tenantName.value = newVal;
    }
  },
  { immediate: true },
);
</script>

<template>
  <div class="p-5 space-y-4">
    <Card>
      <Form layout="inline" :model="filters">
        <Form.Item label="关键词">
          <Input
            v-model:value="filters.search"
            allow-clear
            placeholder="报名编号 / 姓名 / 手机号"
            style="width: 240px"
            @pressEnter="handleSearch"
          />
        </Form.Item>
        <Form.Item label="报名状态">
          <Select
            v-model:value="filters.status"
            :options="statusOptions"
            allow-clear
            placeholder="请选择"
            style="width: 160px"
          />
        </Form.Item>
        <Form.Item label="报名日期">
          <DatePicker.RangePicker
            v-model:value="appliedRange"
            allow-clear
            value-format="YYYY-MM-DD"
            style="width: 260px"
            :placeholder="['开始日期', '结束日期']"
          />
        </Form.Item>
        <Form.Item>
          <Space>
            <Button type="primary" @click="handleSearch" :loading="loading">查询</Button>
            <Button @click="handleReset">重置</Button>
          </Space>
        </Form.Item>
      </Form>
    </Card>

    <Card :title="cardTitle" :bordered="false">
      <template #extra>
        <Space>
          <Button type="primary" ghost @click="openManualModal">手动录入</Button>
          <Button @click="handleBack">返回任务列表</Button>
        </Space>
      </template>
      <Table
        :columns="columns"
        :data-source="applications"
        :loading="loading"
        row-key="id"
        :pagination="tablePagination"
        :scroll="{ x: 1200 }"
        @change="handleTableChange"
      />
    </Card>

    <Modal
      v-model:open="manualModalVisible"
      title="手动录入合同与报名"
      :confirm-loading="manualSubmitting"
      ok-text="录入"
      cancel-text="取消"
      @ok="handleManualSubmit"
      @cancel="resetManualModal"
    >
      <Form layout="vertical">
        <Form.Item label="搜索并选择C端用户">
          <Space class="w-full" wrap>
            <Input
              v-model:value="manualFreelancerKeyword"
              placeholder="请输入姓名或手机号"
              style="width: 220px"
              @pressEnter="handleFreelancerSearch"
            />
            <Button type="primary" @click="handleFreelancerSearch" :loading="manualFreelancerLoading">
              搜索
            </Button>
          </Space>
          <Select
            v-model:value="manualSelectedFreelancerId"
            :options="manualFreelancerOptions"
            style="width: 100%; margin-top: 12px"
            placeholder="请选择搜索结果中的C端用户"
            :loading="manualFreelancerLoading"
            show-search
            option-filter-prop="label"
          />
        </Form.Item>
        <Form.Item label="合同扫描件">
          <Upload.Dragger
            name="contract_file"
            :before-upload="() => false"
            :file-list="manualFileList"
            :on-change="handleManualUploadChange"
            :on-remove="handleManualUploadRemove"
            :max-count="1"
            accept=".pdf,.jpg,.jpeg,.png"
          >
            <p class="ant-upload-drag-icon">
              <i class="i-lucide:upload" />
            </p>
            <p class="ant-upload-text">点击或拖拽扫描件到此处上传</p>
            <p class="ant-upload-hint">支持 PDF、JPG、PNG，单个文件不超过 10MB</p>
          </Upload.Dragger>
        </Form.Item>
      </Form>
    </Modal>

    <Modal
      v-model:open="previewModalVisible"
      :title="previewTitle"
      :footer="null"
      width="80%"
      destroy-on-close
      @cancel="closePreviewModal"
      @afterClose="closePreviewModal"
    >
      <div
        v-if="previewLoading"
        style="height: 480px; display: flex; align-items: center; justify-content: center;"
      >
        正在加载合同...
      </div>
      <iframe
        v-else-if="previewUrl"
        :src="previewUrl"
        style="width: 100%; height: 480px; border: none;"
      ></iframe>
      <p v-else class="text-gray-500">暂无合同文件。</p>
    </Modal>
  </div>
</template>
